package servlets;

import com.google.gson.Gson;
import entity.Absence;
import entity.ResponseData;
import utils.DBUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

@WebServlet({"/absences", "/absences/*"})
public class AbsenceServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private final Gson gson = new Gson();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        handleCors(response);
        response.setContentType("application/json;charset=UTF-8");

        String pathInfo = request.getPathInfo();
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            conn = DBUtils.getConnection();

            if (pathInfo == null || pathInfo.equals("/")) {
                // 获取所有旷寝记录或按条件查询
                String date = request.getParameter("date");
                String dormBuildName = request.getParameter("dormBuildName");
                String studentName = request.getParameter("studentName");
                String studentId = request.getParameter("studentId");

                StringBuilder sql = new StringBuilder("SELECT * FROM t_absence WHERE 1=1");
                List<Object> params = new ArrayList<>();

                if (date != null && !date.isEmpty()) {
                    sql.append(" AND absenceDate = ?");
                    params.add(Date.valueOf(date));
                }
                if (dormBuildName != null && !dormBuildName.isEmpty()) {
                    sql.append(" AND dormBuildName LIKE ?");
                    params.add("%" + dormBuildName + "%");
                }
                if (studentName != null && !studentName.isEmpty()) {
                    sql.append(" AND studentName LIKE ?");
                    params.add("%" + studentName + "%");
                }
                if (studentId != null && !studentId.isEmpty()) {
                    sql.append(" AND studentId = ?");
                    params.add(Integer.parseInt(studentId));
                }
                sql.append(" ORDER BY absenceDate DESC, createTime DESC");

                pstmt = conn.prepareStatement(sql.toString());
                for (int i = 0; i < params.size(); i++) {
                    pstmt.setObject(i + 1, params.get(i));
                }

                rs = pstmt.executeQuery();

                List<Absence> absences = new ArrayList<>();
                while (rs.next()) {
                    Absence absence = mapResultSetToAbsence(rs);
                    absences.add(absence);
                }

                response.getWriter().write(gson.toJson(absences));
            } else {
                // 获取单个旷寝记录详情
                String idStr = pathInfo.substring(1);
                int absenceId = Integer.parseInt(idStr);

                String sql = "SELECT * FROM t_absence WHERE absenceId = ?";
                pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, absenceId);
                rs = pstmt.executeQuery();

                if (rs.next()) {
                    Absence absence = mapResultSetToAbsence(rs);
                    response.getWriter().write(gson.toJson(absence));
                } else {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    response.getWriter().write(gson.toJson(new ResponseData(false, "旷寝记录未找到")));
                }
            }
        } catch (NumberFormatException e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write(gson.toJson(new ResponseData(false, "无效的ID格式")));
        } catch (Exception e) {
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        handleCors(response);
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");

        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = request.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        }

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            Absence newAbsence = gson.fromJson(jsonBuilder.toString(), Absence.class);

            // 验证必填字段
            if (newAbsence.getStudentId() == 0 || newAbsence.getStudentName() == null ||
                    newAbsence.getDormBuildName() == null || newAbsence.getDormName() == null ||
                    newAbsence.getAbsenceDate() == null) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write(gson.toJson(new ResponseData(false, "缺少必填字段")));
                return;
            }

            // 设置登记人和创建时间
            String registrar = request.getRemoteUser();
            if (registrar == null || registrar.isEmpty()) {
                registrar = "system";
            }
            newAbsence.setRegistrar(registrar);

            String sql = "INSERT INTO t_absence (studentId, studentName, dormBuildName, dormName, " +
                    "absenceDate, reason, registrar) VALUES (?, ?, ?, ?, ?, ?, ?)";
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            pstmt.setInt(1, newAbsence.getStudentId());
            pstmt.setString(2, newAbsence.getStudentName());
            pstmt.setString(3, newAbsence.getDormBuildName());
            pstmt.setString(4, newAbsence.getDormName());
            pstmt.setDate(5, new java.sql.Date(newAbsence.getAbsenceDate().getTime()));
            pstmt.setString(6, newAbsence.getReason());
            pstmt.setString(7, newAbsence.getRegistrar());

            int affectedRows = pstmt.executeUpdate();

            if (affectedRows > 0) {
                try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
                    if (generatedKeys.next()) {
                        newAbsence.setAbsenceId(generatedKeys.getInt(1));
                    }
                }
                // 修正为2个参数：success和message
                response.getWriter().write(gson.toJson(new ResponseData(true, "旷寝记录添加成功")));
            } else {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        } catch (Exception e) {
        }
    }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException {
        handleCors(response);
        request.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");

        String pathInfo = request.getPathInfo();
        if (pathInfo == null || pathInfo.equals("/")) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write(gson.toJson(new ResponseData(false, "必须指定旷寝记录ID")));
            return;
        }

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            int absenceId = Integer.parseInt(pathInfo.substring(1));

            StringBuilder jsonBuilder = new StringBuilder();
            try (BufferedReader reader = request.getReader()) {
                String line;
                while ((line = reader.readLine()) != null) {
                    jsonBuilder.append(line);
                }
            }

            Absence updatedAbsence = gson.fromJson(jsonBuilder.toString(), Absence.class);

            // 验证必填字段
            if (updatedAbsence.getStudentId() == 0 || updatedAbsence.getStudentName() == null ||
                    updatedAbsence.getDormBuildName() == null || updatedAbsence.getDormName() == null ||
                    updatedAbsence.getAbsenceDate() == null) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write(gson.toJson(new ResponseData(false, "缺少必填字段")));
                return;
            }

            String sql = "UPDATE t_absence SET studentId = ?, studentName = ?, dormBuildName = ?, " +
                    "dormName = ?, absenceDate = ?, reason = ? WHERE absenceId = ?";
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, updatedAbsence.getStudentId());
            pstmt.setString(2, updatedAbsence.getStudentName());
            pstmt.setString(3, updatedAbsence.getDormBuildName());
            pstmt.setString(4, updatedAbsence.getDormName());
            pstmt.setDate(5, new java.sql.Date(updatedAbsence.getAbsenceDate().getTime()));
            pstmt.setString(6, updatedAbsence.getReason());
            pstmt.setInt(7, absenceId);

            int affectedRows = pstmt.executeUpdate();

            if (affectedRows > 0) {
                updatedAbsence.setAbsenceId(absenceId);
                // 修正为2个参数：success和message
                response.getWriter().write(gson.toJson(new ResponseData(true, "旷寝记录更新成功")));
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write(gson.toJson(new ResponseData(false, "旷寝记录未找到")));
            }
        } catch (NumberFormatException e) {
        } catch (Exception e) {
        }
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException {
        handleCors(response);
        response.setContentType("application/json;charset=UTF-8");

        String pathInfo = request.getPathInfo();
        if (pathInfo == null || pathInfo.equals("/")) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write(gson.toJson(new ResponseData(false, "必须指定旷寝记录ID")));
            return;
        }

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            int absenceId = Integer.parseInt(pathInfo.substring(1));

            String sql = "DELETE FROM t_absence WHERE absenceId = ?";
            conn = DBUtils.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, absenceId);

            int affectedRows = pstmt.executeUpdate();

            if (affectedRows > 0) {
                response.getWriter().write(gson.toJson(new ResponseData(true, "旷寝记录删除成功")));
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.getWriter().write(gson.toJson(new ResponseData(false, "旷寝记录未找到")));
            }
        } catch (NumberFormatException e) {
        } catch (Exception e) {
        } finally {
            DBUtils.close(conn, pstmt, null);
        }
    }

    @Override
    protected void doOptions(HttpServletRequest request, HttpServletResponse response) {
        handleCors(response);
        response.setStatus(HttpServletResponse.SC_OK);
    }

    private void handleCors(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Custom-Header");
        response.setHeader("Access-Control-Max-Age", "3600");
    }

    private Absence mapResultSetToAbsence(ResultSet rs) throws SQLException {
        Absence absence = new Absence();
        absence.setAbsenceId(rs.getInt("absenceId"));
        absence.setStudentId(rs.getInt("studentId"));
        absence.setStudentName(rs.getString("studentName"));
        absence.setDormBuildName(rs.getString("dormBuildName"));
        absence.setDormName(rs.getString("dormName"));
        absence.setAbsenceDate(rs.getDate("absenceDate"));
        absence.setReason(rs.getString("reason"));
        absence.setRegistrar(rs.getString("registrar"));
        absence.setCreateTime(rs.getTimestamp("createTime"));
        return absence;
    }
}